﻿using System;
using System.IO;
using ITU.MDD.CPML;
using ITU.MDD.UPML;
using Microsoft.VisualStudio.Modeling;

namespace MDD.PML.Utility
{
    /// <summary>
    /// This class is used to create an M2M transforming PSM to PIM
    /// </summary>
    internal class PSM2PIM
    {
        private static Store pimstore = null;
        private static Store psmstore = null;
        private static PageModelPackage pim = null;
        private static DocumentTypePackage psm = null;

        /// <summary>
        /// Deserializes the PSM file
        /// </summary>
        /// <param name="modelPath">The path to the PSM file</param>
        internal static void Transform(string modelPath)
        {
            psmstore = new Store(typeof(UPMLDomainModel));

            using (Transaction trans = psmstore.TransactionManager.BeginTransaction("Load PSM"))
            {
                psm = UPMLSerializationHelper.Instance.LoadModel(psmstore, @modelPath, null, null, null);
                CreateCPML();
            }
        }

        /// <summary>
        /// Create the PIM from the PSM
        /// </summary>
        private static void CreateCPML()
        {
            pimstore = new Store(typeof(CPMLDomainModel));

            using (Transaction trans = pimstore.TransactionManager.BeginTransaction("Create PIM from Umbraco PSM"))
            {
                pim = new PageModelPackage(pimstore);
                if (psm.DocumentTypes.Count > 0)
                {
                    foreach (DocumentType parent in psm.DocumentTypes)
                    {
                        if (parent.Parent.Count == 0)
                        {
                            PageModel pagemodel = new PageModel(pimstore) 
                            {
                                InternalName = parent.Name,
                                DisplayName = parent.Alias,
                                Description = parent.Description,
                            };

                            if (parent.GenericProperties.Count > 0)
                            {
                                foreach (GenericProperty attribute in parent.GenericProperties)
                                {
                                    CPMLAttribute prop = new CPMLAttribute(pimstore) 
                                    {
                                        DisplayName = attribute.Name, 
                                        InternalName = attribute.Alias,
                                        Description = attribute.Description,
                                        Required = attribute.Mandatory,
                                        Type = CreateType(attribute.PropertyType)
                                    };

                                    pagemodel.Attributes.Add(prop);
                                    pim.CPMLAttribute.Add(prop);
                                }
                            }

                            pim.PageModels.Add(pagemodel);

                            if (parent.Children.Count > 0)
                            {
                                foreach (DocumentType child in parent.Children)
                                {
                                    CreateChildPageModel(child, pagemodel);
                                }
                            }
                        }
                    }

                    try
                    {
                        SerializationResult result = new SerializationResult();

                        Char separator = '_';
                        string fileName = string.Format("{0}.cpml", DateTime.Now.ToString()
                            .Replace('/', separator)
                            .Replace(' ', separator)
                            .Replace(':', separator));
                        string filePath = Path.Combine(Directory.GetCurrentDirectory(), fileName);
                        CPMLSerializationHelper.Instance.SaveModel(result, pim, filePath);

                        if (result.Failed)
                        {
                            foreach (SerializationMessage message in result)
                            {
                                Console.WriteLine(message);
                            }
                        }
                    }
                    catch (IOException ex)
                    {
                        throw ex;
                    }
                }
            }
        }

        private static void CreateChildPageModel(DocumentType child, PageModel pagemodel)
        {
            PageModel pagemodelchild = new PageModel(pimstore) 
            { 
                InternalName = child.Name, 
                DisplayName = child.Alias,
                Description = child.Description,
            };

            if (child.GenericProperties.Count > 0)
            {
                foreach (GenericProperty attribute in child.GenericProperties)
                {
                    CPMLAttribute prop = new CPMLAttribute(pimstore) 
                    {
                        DisplayName = attribute.Name,
                        InternalName = attribute.Alias,
                        Description = attribute.Description,
                        Required = attribute.Mandatory,
                        Type = CreateType(attribute.PropertyType)
                    };

                    pagemodelchild.Attributes.Add(prop);
                    pim.CPMLAttribute.Add(prop);
                }
            }

            pagemodel.Children.Add(pagemodelchild);
            pim.PageModels.Add(pagemodelchild);

            if (pagemodel.Children.Count > 0)
            {
                foreach (DocumentType grandchild in child.Children)
                {
                    CreateChildPageModel(grandchild, pagemodelchild);
                }
            }
        }

        private static AttributeType CreateType(GenericPropertyType attributeType)
        {
            switch (attributeType)
            {
                case GenericPropertyType.Boolean:
                    return AttributeType.Boolean;

                case GenericPropertyType.CheckboxList:
                    return AttributeType.CheckBoxes;

                case GenericPropertyType.DatePicker:
                    return AttributeType.Date;

                case GenericPropertyType.DatePickerWithTime:
                    return AttributeType.DateTime;

                case GenericPropertyType.DropdownMultiple:
                    return AttributeType.DropdownMultipleChoice;

                case GenericPropertyType.DropDown:
                    return AttributeType.DropdownSingleChoice;

                case GenericPropertyType.RichTextEditor:
                    return AttributeType.HTMLEditorRich;

                case GenericPropertyType.SimpleEditor:
                    return AttributeType.HTMLEditorSimple;

                case GenericPropertyType.MediaPicker:
                    return AttributeType.Image;

                case GenericPropertyType.Numeric:
                    return AttributeType.Number;

                case GenericPropertyType.Radiobox:
                    return AttributeType.RadioButtons;

                case GenericPropertyType.TextboxMultiple:
                    return AttributeType.TextBox;

                case GenericPropertyType.TextString:
                    return AttributeType.TextLine;

                default:
                    throw new Exception("Attribute mapping error");
            }
        }

        internal static void Umbraco2Psm()
        {
            throw new NotImplementedException();
        }
    }
}